#include <jni.h>
#include <string>
#include <android/log.h>
#include <malloc.h>

extern "C" {
#include "librtmp/rtmp.h"
}

#include "VideoChannel.h"
#include "maniulog.h"
#include "safe_queue.h"
#include "JavaCallHelper.h"

VideoChannel *videoChannel;

bool isStart = false;

pthread_t pid;

SafeQueue<RTMPPacket *> packets;

//推流标志位
bool readyPushing = false;
uint32_t start_time;

void *start(void *args);

void releasePackets(RTMPPacket *&pPacket);


//---------------------------

JavaCallHelper *helper=0;
JavaVM *javaVm=0;


void callback(RTMPPacket *packet){
    LOGE("callback 1");
    if(packet){
        LOGE("callback 2");
        if (packets.size() > 50) {
            LOGE("callback 3");
            //防止网络阻塞导致OOM
            packets.clear();
            LOGE("callback 4");
        }
        LOGE("callback 5");
        packet->m_nTimeStamp = RTMP_GetTime() - start_time;
        LOGE("callback 6");
        packets.push(packet);
        LOGE("callback 7");
    }
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,void *unused){
    javaVm=vm;
    LOGE("保存虚拟机引用");
    return JNI_VERSION_1_4;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1init(JNIEnv *env, jobject thiz) {
    LOGE("native_1init 1");
    helper=new JavaCallHelper(javaVm,env,thiz);

    packets.setReleaseCallback()

    videoChannel = new VideoChannel;
    videoChannel->setVideoCallback(callback);
    videoChannel->javaCallHelper=helper;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1setVideoEncInfo(JNIEnv *env, jobject thiz,
                                                                jint width, jint height, jint fps,
                                                                jint bitrate) {
    LOGE("setVideoEncInfo 1");
    if (videoChannel) {
        videoChannel->setVideoEncInfo(width, height, fps, bitrate);
    }
    LOGE("setVideoEncInfo 2");
}


extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1start(JNIEnv *env, jobject thiz, jstring path_) {

    //连接rtmp
    if (isStart) {
        return;
    }
    const char *path = env->GetStringUTFChars(path_, 0);

    char *url = new char[strlen(path) + 1];
    strcpy(url, path);
    isStart = true;


    pthread_create(&pid, NULL, start, url);


    env->ReleaseStringUTFChars(path_, path);

}


void *start(void *args) {
    char *url = static_cast<char *>(args);
    RTMP *rtmp = 0;
    do {
        rtmp = RTMP_Alloc();
        if (!rtmp) {
            LOGE("rtmp创建失败");
            break;
        }
        RTMP_Init(rtmp);
        //设置超时时间 5s
        rtmp->Link.timeout = 5;
        int ret = RTMP_SetupURL(rtmp, url);
        if (!ret) {
            LOGE("rtmp设置地址失败:%s", url);
            break;
        }
        //开启输出模式
        RTMP_EnableWrite(rtmp);
        ret = RTMP_Connect(rtmp, 0);
        if (!ret) {
            LOGE("rtmp连接地址失败:%s", url);
            break;
        }
        ret = RTMP_ConnectStream(rtmp, 0);

        LOGE("rtmp连接成功----------->:%s", url);
        if (!ret) {
            LOGE("rtmp连接流失败:%s", url);
            break;
        }
        //准备好了 可以开始推流了
        readyPushing = true;
        //记录一个开始推流的时间
        start_time = RTMP_GetTime();
        packets.setWork(1);
        RTMPPacket *packet = 0;
        //循环从队列取包 然后发送
        while (isStart) {
            LOGE("发送数据准备 1");
            packets.pop(packet);
            LOGE("发送数据准备 2");

            if (!isStart) {
                break;
            }
            if (!packet) {
                continue;
            }
            // 给rtmp的流id
            packet->m_nInfoField2 = rtmp->m_stream_id;
            //发送包 1:加入队列发送
            ret = RTMP_SendPacket(rtmp, packet, 1);
            releasePackets(packet);
            if (!ret) {
                LOGE("发送数据失败");
                break;
            }
        }
        releasePackets(packet);
    } while (0);
    if (rtmp) {
        RTMP_Close(rtmp);
        RTMP_Free(rtmp);
    }
    delete url;
    return 0;
}

void releasePackets(RTMPPacket *&packet) {
    if (packet) {
        RTMPPacket_Free(packet);
        delete packet;
        packet = 0;
    }
}

extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1pushVideo(JNIEnv *env, jobject thiz,jbyteArray data_) {

    if (!videoChannel&&!readyPushing){
        return;
    }

    jbyte  *data=env->GetByteArrayElements(data_,0);
    videoChannel->encodeData(data);
    env->ReleaseByteArrayElements(data_,data,0);


}extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1stop(JNIEnv *env, jobject thiz) {


}extern "C"
JNIEXPORT void JNICALL
Java_com_maniu_bilirtmp_live_LivePusher_native_1release(JNIEnv *env, jobject thiz) {


}